package com.devicemantra.coordinate.interfaces.http;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;

import com.devicemantra.coordinate.dataobjects.Logo;
import com.devicemantra.coordinate.exceptions.operations.CException;
import com.devicemantra.coordinate.exceptions.operations.CFileParameterNotFoundException;
import com.devicemantra.coordinate.exceptions.operations.CIOException;
import com.devicemantra.coordinate.exceptions.operations.CParameterNotFoundException;
import com.google.appengine.api.datastore.Blob;
import com.oreilly.servlet.*;
import com.oreilly.servlet.multipart.*;

public class CMultipartFormReader {
	
	FilePart mFilePart = null;
	ParamPart mParamPart = null;
	HttpServletRequest mHTTPServletReq;
	HttpServletResponse mHTTPServletResp;
	ArrayList<ParamPart> mParameterList = null;
	ArrayList<FilePart> mFileList = null;
	ArrayList<ByteArrayOutputStream> mByteArrayOutputStreamList = null;
	
	public CMultipartFormReader(HttpServletRequest req) {
		
		mHTTPServletReq = req;
		mParameterList = new ArrayList<ParamPart>();
		mFileList = new ArrayList<FilePart>();
		mByteArrayOutputStreamList = new ArrayList<ByteArrayOutputStream>();
	}
	
	public void processForm() throws CIOException {
		try {
			MultipartParser lMultipartParser = new MultipartParser(mHTTPServletReq,1000000);
			Part lPart = null; 
				while( (lPart = lMultipartParser.readNextPart()) != null ) 
				{
					if( lPart == null )
						break;
				
					/* Check whether this Part is a file or a form field ? */
					if( lPart.isParam() )
					{
						ParamPart lParamPart = (ParamPart ) lPart;
						/* Update the list */
						mParameterList.add(lParamPart);
					}
					else 
					{
						/* It's a file , process the file */
						FilePart lFilePart = (FilePart)lPart;
						InputStream lInputStream = lFilePart.getInputStream();
						byte[] lBytes = null;
						
						try {
								lBytes = IOUtils.toByteArray(lInputStream);
						} catch (IOException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
						ByteArrayOutputStream lByteArrayOstream = new ByteArrayOutputStream();
						lByteArrayOstream.write(lBytes);
						System.out.println("Byte array length is " + lBytes.length);
						mByteArrayOutputStreamList.add(lByteArrayOstream);
						/* make it available for Garbage collection */
						lBytes = null; 
						
						mFileList.add(lFilePart);
					}
				}
			
		} catch(IOException e) {
			throw new CIOException("ERROR: Processing multipartform : " + e.getMessage());
		}
		
	}

	public int getNumParameters()
	{
		return mParameterList.size();
	}
	
	public int getNumFiles()
	{
		return mFileList.size();
	}
	
	public String getParameter(String pName) throws CException, CParameterNotFoundException 
	{
		String lValue = null;
		int lLen = mParameterList.size();
		for(int lCounter = 0; lCounter < lLen; lCounter++)
		{
			ParamPart lParamPart = mParameterList.get(lCounter);
			if(lParamPart.getName().equals(pName))
			{
				try {
					lValue = lParamPart.getStringValue();
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new CException(e.getMessage());
				}
			}
		}
		/* We could not find the parameter the client is looking for */
		if(null == lValue )
			throw new CParameterNotFoundException("ERROR: Could not find the parameter " + pName);
			
		return lValue;
	}
	
	public FilePart getFile(String pName) throws CFileParameterNotFoundException 
	{
		FilePart lFilePart = null;
		int lLen = mFileList.size();
		for(int lCounter = 0; lCounter < lLen; lCounter++)
		{
			lFilePart = mFileList.get(lCounter);
			if(lFilePart.getName().equals(pName))
				break;
		}
		/* We could not find the file the client is looking for */
		if(null == lFilePart )
			throw new CFileParameterNotFoundException("ERROR: Could not find the parameter " + pName);
		
		return lFilePart;
	}
	
	public byte[] getFileAsBytes(String pName) throws CFileParameterNotFoundException 
	{
		FilePart lFilePart = null;
		byte[] lBytes = null;
		ByteArrayOutputStream lBOstream = null;
		int lLen = mFileList.size();
		for(int lCounter = 0; lCounter < lLen; lCounter++)
		{
			lFilePart = mFileList.get(lCounter);
			if(lFilePart.getName().equals(pName)) {
				lBOstream = mByteArrayOutputStreamList.get(lCounter);
				break;
			}
		}
		/* We could not find the file the client is looking for */
		if(null == lBOstream )
			throw new CFileParameterNotFoundException("ERROR: Could not find the parameter " + pName);
		
		return lBOstream.toByteArray();
	}


}
